<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Middleware;

use App\Log\TelephoneBalanceLog;
use App\Job\ApiLogJob;
use App\Model\User;
use App\Service\QueueService;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
use Hyperf\HttpServer\Router\Dispatched;
use Hyperf\Utils\ApplicationContext;
use HyperfExtension\Jwt\Contracts\JwtFactoryInterface;
use HyperfExtension\Jwt\Contracts\ManagerInterface;
use HyperfExtension\Jwt\Exceptions\JwtException;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class ApiAuthMiddleware implements MiddlewareInterface
{
    /**
     * @var ContainerInterface
     */
    protected $container;

    /**
     * 提供了对 JWT 编解码、刷新和失活的能力。
     *
     * @var \HyperfExtension\Jwt\Contracts\ManagerInterface
     */
    protected $manager;

    /**
     * 提供了从请求解析 JWT 及对 JWT 进行一系列相关操作的能力。
     *
     * @var \HyperfExtension\Jwt\Jwt
     */
    protected $jwt;

    /**
     * @var RequestInterface
     */
    protected $request;

    /**
     * @var HttpResponse
     */
    protected $response;

    /**
     * @var QueueService
     */
    protected $service;

    public function __construct(
        ContainerInterface $container,
        RequestInterface $request,
        HttpResponse $response,
        ManagerInterface $manager,
        JwtFactoryInterface $jwtFactory,
        QueueService $queueService
    ) {
        $this->container = $container;
        $this->jwt = $jwtFactory->make();
        $this->manager = $manager;
        $this->response = $response;
        $this->request = $request;
        $this->service = $queueService;
    }

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {

     if (!in_array($request->getUri()->getPath(), ['/api/v1/file/image'])){
        $appVersion = $request->getHeaderLine('X-App-Version');
        // TelephoneBalanceLog::info('appVersion:::::::' . $appVersion);
        if (!$appVersion){

            $data = ['code' => 10000, 'msg' => '请升级最新版本', 'data' => []];
            return $this->response->withStatus(200)->json($data);
        }

        if ($appVersion < \Hyperf\Support\env('X_App_Version')) {
            $data = ['code' => 10000, 'msg' => '请升级最新版本', 'data' => []];
            return $this->response->withStatus(200)->json($data);
        }
     }

        $authorization = $request->getHeader('Authorization');

        if (! $authorization) {
            $data = ['code' => 10001, 'msg' => 'Authorization不存在或者格式不对', 'data' => []];

            return $this->response->withStatus(401)->json($data);
        }

        try {
            $payload = $this->jwt->parseToken()->checkOrFail();
        } catch (JwtException $e) {
            $data = ['code' => 10002, 'msg' => '令牌已过期', 'data' => []];

            return $this->response->withStatus(401)->json($data);
        }
        $userId = $payload->get('sub');

        if (! $userId) {
            $data = ['code' => 10003, 'msg' => '请前去登录', 'data' => []];

            return $this->response->withStatus(401)->json($data);
        }

        // 取出用户信息
        $user = User::find($userId);

        if (! $user) {
            $data = ['code' => 10003, 'msg' => '令牌已失效, 请重新获取', 'data' => []];
            return $this->response->withStatus(401)->json($data);
        }

        if ($user->is_ban == 1) {
            $data = ['code' => 10003, 'msg' => '用户已封禁', 'data' => []];
            return $this->response->withStatus(401)->json($data);
        }

        // 将新的请求对象设置到上下文中
        set_app_user($user);

        $this->writeLog($request);
        return $handler->handle($request);
    }

    public function writeLog(ServerRequestInterface $request)
    {
        // if ($request->getMethod() != 'GET') {
            $requestH = ApplicationContext::getContainer()->get(RequestInterface::class);
            $header = $requestH->getHeader('User-Agent');
            $routerHander = $request->getAttribute(Dispatched::class)->handler;

            $data = [
                'path' => $requestH->getUri()->getPath(),
                'action' => $routerHander->callback[0] . '::' . $routerHander->callback[1],
                'method' => $requestH->getMethod(),
                'params' => json_encode($requestH->all(), JSON_UNESCAPED_UNICODE),
                'remote_ip' => get_client_ip(),
                'agent' => !empty($header) ? $header[0] : '',
                'user_id' => get_app_user()->id,
                'user_name' => get_app_user()->nick_name,
                'operation' => get_app_user()->nick_name . $routerHander->options['operation'],
                'type' => '',
            ];

            $this->service->push(ApiLogJob::class, $data);
        // }
    }
}
